
#include <BFont>
#include <BImage>
#include <BPainter>
#include <BMouseEvent>

#include <BButtonGroup>
#include "member_BButtonGroup.h"
#include "member_BButton.h"

using namespace BWE;

#define member					(*(member_BButtonGroup*)_ptr)
#define member_allocate()		_ptr = new member_BButtonGroup(this)
#define member_release()		delete (member_BButtonGroup*)_ptr

BButtonGroup::BButtonGroup(const BString& name) : BObject(name)
{
	member_allocate();
}
BButtonGroup::BButtonGroup(SelectMode selectMode, const BString& name) : BObject(name)
{
	member_allocate();
	member.selectMode = selectMode;
}
BButtonGroup::~BButtonGroup()
{
	member_release();
}

BButton* BButtonGroup::addButton(const BString& text, BWidget* parent)
{
	BButton* button = new BButton(text, parent);
	addButton(button);
	return button;
}
BButton* BButtonGroup::addButton(Graph graph, const BString& text, BWidget* parent)
{
	BButton* button = new BButton(graph, text, parent);
	addButton(button);
	return button;
}
BButton* BButtonGroup::addButton(BIcon* icon, const BString& text, BWidget* parent)
{
	BButton* button = new BButton(icon, text, parent);
	addButton(button);
	return button;
}
BButton* BButtonGroup::addButton(BImage* image, const BString& text, BWidget* parent)
{
	BButton* button = new BButton(image, text, parent);
	addButton(button);
	return button;
}

bool BButtonGroup::addButton(BButton* button)
{
	if (button && !member.buttons.contain(button))
	{
		button->setCheckable(true);
		member.buttons.append(button);
		member.connect(button, Signal_Pressed, &member_BButtonGroup::slotButtonPressed);
		member.connect(button, Signal_Clicked, &member_BButtonGroup::slotButtonClicked);
		member.connect(button, Signal_Toggled, &member_BButtonGroup::slotButtonToggled);
		member.connect(button, Signal_Checked, &member_BButtonGroup::slotButtonChecked);
		this->emit(Signal_Insert, button);
		return true;
	}
	return false;
}
bool BButtonGroup::insertButton(int pos, BButton* button)
{
	if (!button)
		return false;
	if (member.buttons.contain(button))
	{
		int index = member.buttons.find(button);
		return member.buttons.move(index, pos);
	}
	else
	{
		button->setCheckable(true);
		member.buttons.insert(pos, button);
		member.connect(button, Signal_Pressed, &member_BButtonGroup::slotButtonPressed);
		member.connect(button, Signal_Clicked, &member_BButtonGroup::slotButtonClicked);
		member.connect(button, Signal_Toggled, &member_BButtonGroup::slotButtonToggled);
		member.connect(button, Signal_Checked, &member_BButtonGroup::slotButtonChecked);
		this->emit(Signal_Insert, button);
		return true;
	}
	return false;
}
bool BButtonGroup::removeButton(BButton* button)
{
	if (!button)
		return false;
	if (member.buttons.contain(button))
	{
		if (member.checkedButtons.remove(button))
		{
			button->setChecked(false);
		}
		BHolder<BButton> holder(button);
		member.disconnect(button);
		member.buttons.remove(button);
		this->emit(Signal_Remove, button);
		return true;
	}
	return false;
}
bool BButtonGroup::clearButtons()
{
	if (member.buttons.size())
	{
		while (member.checkedButtons.size())
		{
			BButton* button = member.checkedButtons.first();
			button->setChecked(false);
		}
		member.checkedButtons.clear();
		while (BButton* button = member.buttons.last())
		{
			BHolder<BButton> holder(button);
			member.disconnect(button);
			member.buttons.remove(button);
			this->emit(Signal_Remove, button);
		}
		member.buttons.clear();
		emit(Signal_Clear);
		return true;
	}
	return false;
}

void BButtonGroup::setExclusive(bool exclusive)
{
	if (member.exclusive != exclusive)
	{
		member.exclusive = exclusive;
		bool selectable = member.selectMode & Select_Single & Select_Multiple;
		if (selectable && member.exclusive && member.buttons.size())
		{
			if (member.checkedButtons.empty())
			{
				member.buttons[0]->setChecked(true);
			}
		}
	}
}
bool BButtonGroup::exclusive() const
{
	return member.exclusive;
}

void BButtonGroup::setSelectMode(SelectMode selectMode)
{
	if (member.selectMode != selectMode)
	{
		member.selectMode = selectMode;
	}
}
SelectMode BButtonGroup::selectMode() const
{
	return member.selectMode;
}

int BButtonGroup::buttonCount() const
{
	return member.buttons.size();
}
BButton* BButtonGroup::button(int index)
{
	return member.buttons(index);
}
const BButton* BButtonGroup::button(int index) const
{
	return member.buttons(index);
}
BButton* BButtonGroup::button(const BString& name)
{
	for (int i = 0; i < member.buttons.size(); i++)
	{
		if (member.buttons[i]->name() == name)
			return member.buttons[i];
	}
	return 0;
}
const BButton* BButtonGroup::button(const BString& name) const
{
	for (int i = 0; i < member.buttons.size(); i++)
	{
		if (member.buttons[i]->name() == name)
			return member.buttons[i];
	}
	return 0;
}

BButton* BButtonGroup::buttonOfText(const BString& text)
{
	for (int i = 0; i < member.buttons.size(); i++)
	{
		if (member.buttons[i]->text() == text)
			return member.buttons[i];
	}
	return 0;
}
const BButton* BButtonGroup::buttonOfText(const BString& text) const
{
	for (int i = 0; i < member.buttons.size(); i++)
	{
		if (member.buttons[i]->text() == text)
			return member.buttons[i];
	}
	return 0;
}

BButton* BButtonGroup::buttonOfAsset(const BValue& value)
{
	for (int i = 0; i < member.buttons.size(); i++)
	{
		if (member.buttons[i]->asset() == value)
			return member.buttons[i];
	}
	return 0;
}
const BButton* BButtonGroup::buttonOfAsset(const BValue& value) const
{
	for (int i = 0; i < member.buttons.size(); i++)
	{
		if (member.buttons[i]->asset() == value)
			return member.buttons[i];
	}
	return 0;
}

int BButtonGroup::checkedCount() const
{
	return member.checkedButtons.size();
}
BButton* BButtonGroup::checkedButton(int index) const
{
	return member.checkedButtons(index);
}
void BButtonGroup::clearSelection()
{
	while (member.checkedButtons.size())
	{
		BButton* button = member.checkedButtons.first();
		button->setChecked(false);
	}
}
